import MapboxDraw from "@mapbox/mapbox-gl-draw";
import { MapboxDrawExtends } from "./modes/MapboxDrawExtends";
import MapboxEdit from "./edit/index";

import {
  renderFeatureLayer,
  updateFeatureLayer,
  updateFeatureLayerStyles,
  getModeType,
} from "./renders/index";

import drawIconSrc from "./images/draw-icon.png";
import rotateIconSrc from "./images/rotate.png";
import scaleIconSrc from "./images/scale.png";

export default class MapboxDraw2 {
  constructor({ map, canEdit }) {
    this.map = map;
    this.canEdit = canEdit || true;
    this.draw = null;
    this.store = {};
    this.mode = null;
    this.edit = null;
    this.clickFunc = null;
    this.selectedIds = [];

    this.events = [];

    this.init();
  }

  init() {
    const draw = new MapboxDraw({
      displayControlsDefault: false,
      userProperties: true,
      modes: {
        ...MapboxDraw.modes,
        ...MapboxDrawExtends,
      },
    });
    this.draw = draw;

    this.map.addControl(draw);

    this.registerIcon({ iconName: "draw-icon", iconUrl: drawIconSrc });

    if (this.canEdit) {
      this.registerIcon({ iconName: "rotate-icon", iconUrl: rotateIconSrc });
      this.registerIcon({ iconName: "scale-icon", iconUrl: scaleIconSrc });

      // 编辑之后更新回调函数
      const updateFeatureLayerFunc = this.updateFeatureLayerById.bind(this);
      this.edit = new MapboxEdit(this.map, { updateFeatureLayerFunc });
    }
  }

  bindEvents(eventName, callback) {
    if (eventName === "draw.create") {
      const func = this.onCreateComplete.bind(this, callback);
      this.map.on("draw.create", func);

      this.events.push({
        eventName: "draw.create",
        func: func,
      });
    }

    if (eventName === "draw.select") {
      this.map.on("draw.select", callback);

      this.events.push({
        eventName: "draw.select",
        func: callback,
      });
    }

    this.clickFunc = this.onClickFeature.bind(this);
    this.map.on("click", this.clickFunc);

    this.events.push({
      eventName: "click",
      func: this.clickFunc,
    });
  }

  registerIcon({ iconName, iconUrl }) {
    const map = this.map;
    // Add a stretchable image that can be used with `icon-text-fit`
    // In this example, the image is 600px wide by 400px high.
    map.loadImage(iconUrl, (error, image) => {
      if (error) throw error;
      if (!map.hasImage(iconName)) {
        map.addImage(iconName, image, {
          // content: [16, 16, 300, 384], // place text over left half of image, avoiding the 16px border
          // stretchX: [[16, 584]], // stretch everything horizontally except the 16px border
          // stretchY: [[16, 384]], // stretch everything vertically except the 16px border
        });
      }
    });
  }

  changeMode(mode) {
    if (mode.includes("edit")) {
      // edit_control edit_pan edit_rotate edit_scale
      this.changeEditMode(mode);
    } else {
      // draw_text draw_icon draw_circle draw_ellipse
      // draw_rectangle draw_polygon draw_line_string
      // draw_attack_arrow draw_double_arrow draw_three_arrow
      this.changeDrawMode(mode);
    }
  }

  changeDrawMode(mode) {
    // mode
    // draw_text draw_icon draw_circle draw_ellipse
    // draw_rectangle draw_polygon draw_line_string
    // draw_attack_arrow draw_double_arrow draw_three_arrow
    this.draw.changeMode(mode);
    this.mode = mode;

    // 绘制时需要解除元素查询绑定
    this.map.off("click", this.clickFunc);
  }

  changeEditMode(mode) {
    // 未触发绘制事件,暂时不切换
    // if (this.mode !== "simple_select") {
    //   this.changeDrawMode("simple_select");
    // }

    this.edit.changeMode(mode);
  }

  getModeTypeById(featureId) {
    if (!featureId) return;

    if (!this.store[featureId]) return;

    const mode = this.store[featureId].mode;
    return getModeType(mode);
  }

  onCreateComplete(callback, evt) {
    // console.log("onCreateComplete--call", evt, callback);
    // 移除默认的绘制要素
    const featureId = evt.features[0].id;
    this.draw.delete(featureId);

    // 绘制自定义要素
    const params = {
      map: this.map,
      mode: this.mode,
      features: evt.features,
    };
    const layerIds = renderFeatureLayer(params);

    // 存储自定义要素信息--mode layerIds
    evt.mode = this.mode;
    evt.layerIds = layerIds;
    evt.isNew = true;
    this.store[featureId] = evt;

    // 触发自定义事件
    callback(evt);

    // 绑定点击事件
    if (this.canEdit) {
      // 绘制完成时会立即触发 click 事件，需要延迟绑定
      setTimeout(() => {
        this.map.on("click", this.clickFunc);
      }, 500);
    }
  }

  onClickFeature(evt) {
    //   console.log("click", e);
    const features = this.map.queryRenderedFeatures(evt.point);
    // console.log(features);

    let mode = "";
    if (features.length > 0) {
      const ids = Object.keys(this.store);
      const idsFilter = ids.filter((id) => {
        const feats = features.filter((feat) => feat.source.includes(id));
        if (feats.length > 0) {
          mode = feats[0].source.split("-")[0];
        }
        return feats.length;
      });

      this.selectedIds = idsFilter;

      for (let i = 0; i < idsFilter.length; i++) {
        // 控制点绘制，目前只有箭头有
        const controlPnts = this.store[idsFilter[i]].controlPnts;
        if (controlPnts) {
          this.edit.updateEditSource(controlPnts);
          break;
        }
      }
    } else {
      this.selectedIds = [];
      this.edit.updateEditSource([]);
    }

    // 借用 mapbox 事件系统，注册选中事件
    this.map.fire("draw.select", { selectedIds: this.selectedIds, mode });
  }

  deleteFeatureLayerById(featureId) {
    // const featureId = this.selectedIds[0];
    const { layerIds } = this.store[featureId];
    layerIds.forEach((layerId) => {
      this.map.removeLayer(layerId);
      this.map.removeSource(layerId);
    });

    if (this.canEdit) {
      this.edit.updateEditSource([]);
    }

    delete this.store[featureId];
  }

  addFeatureLayer(geojson) {
    const map = this.map;
    const properties = geojson.properties;
    // 绘制自定义要素
    const params = {
      map: map,
      mode: properties.mode,
      features: geojson.features,
    };
    const layerIds = renderFeatureLayer(params);
    updateFeatureLayerStyles({ map, layerIds, styles: properties });

    // 存储自定义要素信息--mode layerIds
    const evt = {
      controlPnts: properties.controlPnts,
      mode: properties.mode,
      layerIds,
      features: geojson.features,
      id: properties.itemId,
    };

    this.store[geojson.features[0].id] = evt;
  }

  updateFeatureLayerById(points) {
    // console.log("updateFeatureLayerById", this.selectedIds, points);
    const map = this.map;
    const featureId = this.selectedIds[0];
    const { layerIds, mode } = this.store[featureId];
    this.store[featureId].controlPnts = points;
    updateFeatureLayer({ map, layerIds, points, mode });
  }

  updateFeatureLayerStylesById({ featureId, styles }) {
    const map = this.map;
    const layerIds = this.store[featureId].layerIds;
    updateFeatureLayerStyles({ map, layerIds, styles });
  }

  clearFeatureLayer() {
    const ids = Object.keys(this.store);
    ids.forEach((id) => {
      this.deleteFeatureLayerById(id);
    });
  }

  destroy() {
    this.events.forEach((eventName, func) => {
      this.map.off(eventName, func);
    });

    this.map.removeControl(this.draw);

    this.draw = null;
    this.store = {};
    this.mode = null;
    this.edit = null;
    this.clickFunc = null;
    this.selectedIds = [];
  }
}
